package com.pisolution.scheduler.core.extension;

import com.pisolution.scheduler.core.tuple.Tuple2;

import com.google.common.base.Preconditions;

import javax.annotation.Nonnull;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;

/**
 * 用于载入调度平台的扩展功能包.
 *
 * @author sora
 * @version 0.1.0
 */
public final class ExtensionLoader {
    // -------------------------------------------------------------------------------------------------
    //  扩展功能载入
    // -------------------------------------------------------------------------------------------------

    /**
     * 载入平台的扩展功能包 从这些包中获取同类中优先级最高的扩展包予以载入 如果未找到相应的扩展包 则使用平台自身提供的扩展包.
     *
     * @param clazz 需要载入的扩展包类型.
     * @param <T> 扩展的功能模块类型.
     *
     * @return 该功能模块的扩展包.
     */
    public static <T extends Extension> T loadExtension(@Nonnull final Class<T> clazz) {
        // 1. 以迭代的方式载入功能模块.
        final Iterator<T> extensions = ServiceLoader.load(clazz).iterator();

        // 2. 寻找最高优先级的功能模块.
        Tuple2<Integer, T> storage = new Tuple2<>(Integer.MIN_VALUE, null);

        while (extensions.hasNext()) {
            try {
                final T extension = extensions.next();

                if (extension.priority() > storage.field1) {
                    storage.field1 = extension.priority();
                    storage.field2 = extension;
                }
            } catch (Exception | ServiceConfigurationError ignored) {
                // 载入部分功能模块失败 暂时不予处理此异常.
            }
        }

        // 3. 如果未找到功能模块 则判定为扩展包缺失 (包括自身提供的扩展) 构建出现问题.
        Preconditions.checkNotNull(
            storage.field2,
            "The extension package is missing, perhaps the scheduler platform is built failed."
        );

        return storage.field2;
    }

    // -------------------------------------------------------------------------------------------------

    /** 阻止实例化. */
    private ExtensionLoader() {
    }
}
